package com.boarsoft.dao.sharding.group;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import com.boarsoft.common.Util;
import com.boarsoft.dao.sharding.bean.ShardedEntity;

public abstract class MapShardGroup implements ShardGroup {
	@Autowired
	protected ApplicationContext appCtx;

	/** */
	protected String _default;
	/** */
	protected Map<String, String> map = new HashMap<String, String>();
	/** 通过分组key获取DataSource对象 */
	protected Map<String, DataSource> dataSourceMap = new ConcurrentHashMap<>();

	public void removeDataSource(String key) {
		dataSourceMap.remove(key);
	}

	@Override
	public DataSource getDataSource() {
		if (dataSourceMap.isEmpty()) {
			return null;
		}
		if (dataSourceMap.containsKey(_default)) {
			return dataSourceMap.get(_default);
		}
		for (DataSource ds : dataSourceMap.values()) {
			return ds;
		}
		return null;
	}

	@Override
	public DataSource getDataSource(Object key) {
		String k = _default;
		if (key instanceof String) {
			k = (String) key;
		} else if (key instanceof ShardedEntity) {
			k = ((ShardedEntity) key).shard();
		} else {
			k = key.toString();
		}
		if (Util.strIsNotEmpty(k)) {
			DataSource ds = dataSourceMap.get(k);
			if (ds != null) {
				return ds;
			}
			k = this.match(k);
			return dataSourceMap.get(k);
		}
		return dataSourceMap.get(_default);
	}

	public String match(String key) {
		if (map.containsKey(key)) {
			return map.get(key);
		}
		return map.get(_default);
	}

	public void put(String key, String k) {
		synchronized (dataSourceMap) {
			if (dataSourceMap.containsKey(key)) {
				return;
			}
			if (!dataSourceMap.containsKey(k)) {
				return;
			}
			dataSourceMap.put(key, dataSourceMap.get(k));
		}
	}

	public String getDefault() {
		return _default;
	}

	public void setDefault(String value) {
		this._default = value;
	}

	public Map<String, String> getMap() {
		return map;
	}

	public void setMap(Map<String, String> map) {
		this.map = map;
	}

	public Map<String, DataSource> getDataSourceMap() {
		return dataSourceMap;
	}

	public void setDataSourceMap(Map<String, DataSource> dataSourceMap) {
		this.dataSourceMap = dataSourceMap;
	}
}